#include <buola/gui.h>

#include <buola/xml.h>
#include <buola/gui/cphysicalwindow.h>
#include <buola/image/cgc.h>
#include <buola/gui/ctoolkit.h>

#include <buola/widgets/cbutton.h>
#include "cattachmanager_private.h"
#include <buola/widgets/ctheme.h>

#define OUTER_LIMIT 0.1
#define INNER_LIMIT 0.4

namespace buola { namespace gui {

///////////////////////////////
///////// SDecoration /////////
///////////////////////////////

CAttachManager::SDecoration::SDecoration(SRoot *pRoot)
    :   mRoot(pRoot),
        mElements(CTheme::DECO_MAX),
        mMouseIn(false)
{
    get_default_theme()->PrepareDecoration(this);
    ///\todo see what we can do about this
//     if(pRoot->mManager->Window()->GetPossibleActions()&ACTION_DOCK)
//         mElements|=CTheme::DECO_DOCK;
//     if(pRoot->mManager->Window()->GetPossibleActions()&ACTION_CLOSE)
//         mElements|=CTheme::DECO_CLOSE;
//     if(pRoot->mManager->Window()->GetSizeHints()&HINT_FIXEDSIZE)
//         mElements&=~CTheme::DECO_MAX;
//     if(pRoot->mManager->Window()->GetPossibleActions()&ACTION_MINIMIZE)
//         mElements|=CTheme::DECO_MIN;
}

CAttachManager::SDecoration::~SDecoration()
{
}

///////////////// events //////////////////

int CAttachManager::SDecoration::GetArea(const CPoint_d &pPos)
{
    if(CRect_d(CPoint_d(8,5),CSize_d(14,14)).Contains(pPos))
    {
        return CTheme::DECO_CLOSE&mElements;
    }
    else if(CRect_d(CPoint_d(29,5),CSize_d(14,14)).Contains(pPos))
    {
        return CTheme::DECO_MIN&mElements;
    }
    else if(CRect_d(CPoint_d(50,5),CSize_d(14,14)).Contains(pPos))
    {
        return CTheme::DECO_MAX&mElements;
    }
    else if(CRect_d(CPoint_d(Size().x-22,5),CSize_d(14,14)).Contains(pPos))
    {
        return CTheme::DECO_DOCK&mElements;
    }
    return CTheme::DECO_NONE;
}

void CAttachManager::SDecoration::OnSize(const CGeometryEvent &pE)
{
}

void CAttachManager::SDecoration::OnExpose(const CExposeEvent &pE)
{
    CTheme::EDecoFlags lFlags=mElements;
    if(mMouseIn)
        lFlags|=CTheme::DECO_MOUSEIN;
    ///\todo about the title
    get_default_theme()->DrawDecoration(pE.mGC,CRect_d({0,0},Size()),/*mRoot->mManager->Window()->GetTitle()*/L"",lFlags);
}

void CAttachManager::SDecoration::OnButtonDown(const CMouseEvent &pE)
{
///\todo do we really want this??
/*
    if(pE.mButton==EMouseButton::LEFT)
    {
        mPressedArea=GetArea(pE.mPoint);
        if(mPressedArea==CTheme::DECO_NONE)
            mRoot->mManager->Window()->StartMoveOperation(pE);
    }
*/
}

void CAttachManager::SDecoration::OnButtonUp(const CMouseEvent &pE)
{
///\todo do we really want this??
/*
    if(pE.mButton==EMouseButton::LEFT)
    {
        if(mPressedArea==CTheme::DECO_NONE) return;
        if(mPressedArea==GetArea(pE.mPoint))
        {
            if(mPressedArea==CTheme::DECO_CLOSE)
            {
                mRoot->mManager->Window()->Close();
            }
            else if(mPressedArea==CTheme::DECO_MAX)
            {
                mRoot->mManager->Window()->Maximize();
            }
            else if(mPressedArea==CTheme::DECO_MIN)
            {
                mRoot->mManager->Window()->Iconify();
            }
            else if(mPressedArea==CTheme::DECO_DOCK)
            {
                ///\todo this once we know more
                attach(mRoot->mManager->Window(),ATTACH_SOUTH_OF,get_main_window(),
                       ATTACH_BAR|ATTACH_CLOSE,CSize_d(200,200));
            }
        }
        mPressedArea=CTheme::DECO_NONE;
    }
*/
}

void CAttachManager::SDecoration::OnMouseMove(const CMouseEvent &pE)
{
    if(GetArea(pE.mPoint))
    {
        if(!mMouseIn)
        {
            mMouseIn=true;
            Refresh();
        }
    }
    else
    {
        if(mMouseIn)
        {
            mMouseIn=false;
            Refresh();
        }
    }
}

void CAttachManager::SDecoration::OnMouseIn(const CMouseEvent &pE)
{
}

void CAttachManager::SDecoration::OnMouseOut(const CMouseEvent &pE)
{
    mMouseIn=false;
    Refresh();
}

/////////////////////////////////
///////// SResizeCorner /////////
/////////////////////////////////

CAttachManager::SResizeCorner::SResizeCorner(SRoot *pRoot)
    :    mRoot(pRoot)
{
    SetPaintMode(EPaintMode::INVISIBLE);
    SetPointer(CPointer::STOCK_SIZENWSE);
}

CAttachManager::SResizeCorner::~SResizeCorner()
{
}

////// events //////

void CAttachManager::SResizeCorner::OnButtonDown(const CMouseEvent &pE)
{
    ///\todo see what to do about that (it should probably be a frame feature)
//     if(pE.mButton==EMouseButton::LEFT)
//     {
//         mRoot->mManager->Window()->StartResizeOperation(pE);
//     }
}

////////////////////////
///////// STab /////////
////////////////////////

CAttachManager::STab::STab(STabSplit *pSplit)
    : mSplit(pSplit)
{
    SetBackColor(img::CColor(L"darkgray"));
}

CAttachManager::STab::~STab()
{
}

void CAttachManager::STab::DrawTab(img::CGC *pGC,double pX,double pW,const std::wstring &pText,bool pCur)
{
    if(!pCur)
    {
        pGC->Path().MoveTo(CPoint_d(pX,0.5));
        pGC->Path().LineTo(CPoint_d(pX+5,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+9+pW,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+14+pW,0.5));
        pGC->SetSource(img::CColor(L"darkgray"));
        pGC->Path().Close();
        pGC->FillPath(true);
        pGC->SetSource(img::CColor(L"black"));
        pGC->StrokePath();
    }
    else
    {
        pGC->Path().MoveTo(CPoint_d(pX,0));
        pGC->Path().LineTo(CPoint_d(pX+5,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+9+pW,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+14+pW,0));
        pGC->Path().Close();
        pGC->SetSource(img::rgb8(224,224,224));
        pGC->FillPath();
        pGC->Path().MoveTo(CPoint_d(pX,0.5));
        pGC->Path().LineTo(CPoint_d(pX+5,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+9+pW,Size().y-1.5));
        pGC->Path().LineTo(CPoint_d(pX+14+pW,0.5));
        pGC->SetSource(img::CColor(L"black"));
        pGC->StrokePath();
    }

    pGC->DrawText(CPoint_d(pX+7,(Size().y-2)/2),pText,img::ETextPos::VCENTER);
}

///////////////// events //////////////////

void CAttachManager::STab::OnSize(const CGeometryEvent &pE)
{
}

void CAttachManager::STab::OnExpose(const CExposeEvent &pE)
{
    pE.mGC->SetStockFont(L"small");
    pE.mGC->SetLineWidth(1.0);

    double lCurItemX=0;
    double lCurItemW=0;
    std::wstring lCurItemText;

    double lX=0;

    mRects.clear();

    for(int i=0;i<mSplit->mChildren.size();i++)
    {
        if(!mSplit->mChildren[i]->IsVisible())
        {
            mRects.push_back(CRect_d(0,0,0,0));
            continue;
        }

        std::wstring lTitle=mSplit->mChildren[i]->GetTitle();

        CSize_d lSize=pE.mGC->GetTextExtents(mSplit->mChildren[i]->GetTitle());

        if(i==mSplit->mCurrent)
        {
            lCurItemX=lX;
            lCurItemW=lSize.x;
            lCurItemText=lTitle;
        }
        else
        {
            DrawTab(pE.mGC,lX,lSize.x,lTitle,false);
        }

        mRects.push_back(CRect_d(lX,0,lX+9+lSize.x,Size().y));

        lX+=9+lSize.x;
    }

    pE.mGC->Path().MoveTo(CPoint_d(lX,0.5));
    pE.mGC->Path().LineTo(CPoint_d(Size().x,0.5));
    pE.mGC->SetSource(img::CColor(L"black"));
    pE.mGC->StrokePath();

    DrawTab(pE.mGC,lCurItemX,lCurItemW,lCurItemText,true);
}

void CAttachManager::STab::OnButtonDown(const CMouseEvent &pE)
{
    if(pE.mButton==EMouseButton::LEFT)
    {
        for(int i=0;i<mRects.size();i++)
        {
            if(mRects[i].Contains(pE.mPoint))
            {
                mSplit->OnTab(i);
            }
        }
    }
}

void CAttachManager::STab::OnButtonUp(const CMouseEvent &pE)
{
}

void CAttachManager::STab::OnMouseMove(const CMouseEvent &pE)
{
}

void CAttachManager::STab::OnMouseOut(const CMouseEvent &pE)
{
}

/////////////////////////
///////// SPart /////////
/////////////////////////

CAttachManager::SPart::SPart(CAttachManager *pManager)
                : mManager(pManager),mParent(nullptr),mHidden(false)
{
}

CAttachManager::SPart::~SPart()
{
}

EAttachRelative CAttachManager::SPart::PlaceToRelative(EAttachPlace pPlace)
{
    if(pPlace&ATTACH_WEST)
        return ATTACH_WEST_OF;
    if(pPlace&ATTACH_EAST)
        return ATTACH_EAST_OF;
    if(pPlace&ATTACH_NORTH)
        return ATTACH_NORTH_OF;
    if(pPlace&ATTACH_SOUTH)
        return ATTACH_SOUTH_OF;
    if(pPlace&ATTACH_REPLACECLIENT)
        return ATTACH_REPLACE;
    msg_warn() << "unknown attachment place in PlaceToRelative " << (int)pPlace << "\n";
    return ATTACH_NORTH_OF;
}

EAttachRelative CAttachManager::SPart::GetZone(const CPoint_d &pPos)
{
    double lH=(pPos.x-mRect.l)/mRect.w();
    double lV=(pPos.y-mRect.t)/mRect.h();

    EAttachRelative lZone;

    if(lH<INNER_LIMIT)
    {
        if(lV<INNER_LIMIT)
        {
            //   # |   |
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //     |   |

            if(lH<lV)
            {
                lZone=ATTACH_WEST_OF;
            }
            else
            {
                lZone=ATTACH_NORTH_OF;
            }
        }
        else if(lV<1-INNER_LIMIT)
        {
            //     |   |
            //  ---+---+---
            //   # |   |
            //  ---+---+---
            //     |   |

            lZone=ATTACH_WEST_OF;
        }
        else
        {
            //     |   |
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //   # |   |

            if(lH<1-lV)
            {
                lZone=ATTACH_WEST_OF;
            }
            else
            {
                lZone=ATTACH_SOUTH_OF;
            }
        }
    }
    else if(lH<1-INNER_LIMIT)
    {
        if(lV<INNER_LIMIT)
        {
            //     | # |
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //     |   |

            lZone=ATTACH_NORTH_OF;
        }
        else if(lV<1-INNER_LIMIT)
        {
            //     |   |
            //  ---+---+---
            //     | # |
            //  ---+---+---
            //     |   |

            lZone=ATTACH_TAB_WITH;
        }
        else
        {
            //     |   |
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //     | # |

            lZone=ATTACH_SOUTH_OF;
        }
    }
    else
    {
        if(lV<INNER_LIMIT)
        {
            //     |   | #
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //     |   |

            if((1-lH)<lV)
            {
                lZone=ATTACH_EAST_OF;
            }
            else
            {
                lZone=ATTACH_NORTH_OF;
            }
        }
        else if(lV<1-INNER_LIMIT)
        {
            //     |   |
            //  ---+---+---
            //     |   | #
            //  ---+---+---
            //     |   |

            lZone=ATTACH_EAST_OF;
        }
        else
        {
            //     |   |
            //  ---+---+---
            //     |   |
            //  ---+---+---
            //     |   | #

            if((1-lH)<(1-lV))
            {
                lZone=ATTACH_EAST_OF;
            }
            else
            {
                lZone=ATTACH_SOUTH_OF;
            }
        }
    }

    if(mParent&&mParent!=mManager->mRoot&&
                ((lZone==ATTACH_WEST_OF&&lH<OUTER_LIMIT)||
                 (lZone==ATTACH_EAST_OF&&lH>1-OUTER_LIMIT)||
                 (lZone==ATTACH_NORTH_OF&&lV<OUTER_LIMIT)||
                 (lZone==ATTACH_SOUTH_OF&&lV>1-OUTER_LIMIT)))
    {
        lZone=ATTACH_TO_PARENT;
    }

    return lZone;
}

CRect_d CAttachManager::SPart::GetZoneRect(EAttachRelative pZone)
{
    CRect_d lRect=mRect;

    if(pZone==ATTACH_WEST_OF)
    {
        lRect.r-=(int)(lRect.w()*(1-INNER_LIMIT));
    }
    else if(pZone==ATTACH_EAST_OF)
    {
        lRect.l+=(int)(lRect.w()*(1-INNER_LIMIT));
    }
    else if(pZone==ATTACH_NORTH_OF)
    {
        lRect.b-=(int)(lRect.h()*(1-INNER_LIMIT));
    }
    else if(pZone==ATTACH_SOUTH_OF)
    {
        lRect.t+=(int)(lRect.h()*(1-INNER_LIMIT));
    }
    else if(pZone!=ATTACH_TAB_WITH)    //it is the whole rect for WATT_TAB
    {
        lRect=CRect_d(nUndefined);
    }

    return lRect;
}

void CAttachManager::SPart::FindRelocation(SRelocation &pRelocation,bool /*pDescend*/)
{
    EAttachRelative lZone=GetZone(pRelocation.mPoint);

    if(pRelocation.mRelocated==this)
        return;

    if(GetFlags()&(ATTACH_MENUBAR|ATTACH_TOOLBAR|ATTACH_STATUSBAR|ATTACH_RULERBOX))
        return;

    if(lZone==ATTACH_TO_PARENT)
    {
        mParent->FindRelocation(pRelocation,false);
        return;
    }

    pRelocation.mDestination=this;
    pRelocation.mZone=lZone;
    pRelocation.mRect=GetZoneRect(lZone);
    pRelocation.mTab=(lZone==ATTACH_TAB_WITH);
}

void CAttachManager::SPart::PlaceAttachment(SAttachment *pAttachment,
                                            EAttachPlace pPlace)
{
    AttachHere(pAttachment,PlaceToRelative(pPlace));
}

void CAttachManager::SPart::AttachHere(SAttachment *pAttachment,
                                            EAttachRelative pPlace)
{
    SSplit *lOldParent=mParent;

    if(pPlace==ATTACH_TAB_WITH)
    {
        if(mParent->IsTabSplit())
        {
            mParent->AttachHere(pAttachment,pPlace);
        }
        else
        {
            STabSplit *lSplit=new STabSplit(mManager,this,pAttachment);
            lOldParent->ReplaceChild(this,lSplit);
        }
    }
    else if(pPlace==ATTACH_NORTH_OF)
    {
        SHSplit *lSplit=new SHSplit(mManager,pAttachment,this);
        lSplit->SetPos(0,pAttachment->mDesiredSize.y);
        lOldParent->ReplaceChild(this,lSplit);
    }
    else if(pPlace==ATTACH_SOUTH_OF)
    {
        SHSplit *lSplit=new SHSplit(mManager,this,pAttachment);
        lSplit->SetPos(1,-pAttachment->mDesiredSize.y);
        lOldParent->ReplaceChild(this,lSplit);
    }
    else if(pPlace==ATTACH_WEST_OF)
    {
        SVSplit *lSplit=new SVSplit(mManager,pAttachment,this);
        lSplit->SetPos(0,pAttachment->mDesiredSize.x);
        lOldParent->ReplaceChild(this,lSplit);
    }
    else if(pPlace==ATTACH_EAST_OF)
    {
        SVSplit *lSplit=new SVSplit(mManager,this,pAttachment);
        lSplit->SetPos(1,-pAttachment->mDesiredSize.x);
        lOldParent->ReplaceChild(this,lSplit);
    }
    else if(pPlace&ATTACH_REPLACE)
    {
        SCSplit *lSplit=new SCSplit(mManager,pAttachment,this);
        lOldParent->ReplaceChild(this,lSplit);
    }
}

//////////////////////////
///////// SSplit /////////
//////////////////////////

CAttachManager::SSplit::SSplit(CAttachManager *pManager)
    : SPart(pManager)
{
}

CAttachManager::SSplit::~SSplit()
{
    for(int i=0;i<mChildren.size();i++)
    {
        delete mChildren[i];
    }
}

void CAttachManager::SSplit::FindRelocation(SRelocation &pRelocation,
                                                bool pDescend)
{
    if(pDescend)
    {
        for(int i=0;i<mChildren.size();i++)
        {
            if(!mChildren[i]->IsVisible()) continue;
            if(!mChildren[i]->mRect.Contains(pRelocation.mPoint)) continue;
            mChildren[i]->FindRelocation(pRelocation,true);
            return;
        }
    }

    SPart::FindRelocation(pRelocation,false);
}

void CAttachManager::SSplit::ReshapeHidden()
{
    mHidden=true;
    for (int i=0;i<mChildren.size();i++)
        mChildren[i]->ReshapeHidden();
}

bool CAttachManager::SSplit::IsVisible()
{
    for (int i=0;i<mChildren.size();i++)
        if(mChildren[i]->IsVisible()) return true;
    return false;
}

void CAttachManager::SSplit::AddChild(SPart *pPart)
{
    mChildren.push_back(pPart);
    pPart->mParent=this;

    OnChildAdded(mChildren.size()-1);
}

void CAttachManager::SSplit::RemoveChild(SPart *pPart)
{
    bool lFound=false;

    for(int i=0;i<mChildren.size();i++)
    {
        if(pPart==mChildren[i])
        {
            mChildren.erase(mChildren.begin()+i);
            OnChildRemoved(i);
            lFound=true;
            break;
        }
    }

    if(!lFound)
    {
        return;
    }

    if(mChildren.size()==1)
    {
        if(mParent)
        {
            mParent->ReplaceChild(this,mChildren[0]);
            mChildren.erase(mChildren.begin());
            delete this;
        }
        else
        {
            throw XInternal("removing root in cattachlayoutmanager");
        }
    }
}

void CAttachManager::SSplit::ReplaceChild(SPart *pPart,SPart *pWith)
{
    for(int i=0;i<mChildren.size();i++)
    {
        if(mChildren[i]==pPart)
        {
            mChildren[i]=pWith;
            pWith->mParent=this;
            OnChildReplaced(i);
            break;
        }
    }
}

void CAttachManager::SSplit::SaveChildren(xml::CNode pThis,SSaveHelper *pHelper)
{
    for(int i=0;i<mChildren.size();i++)
    {
        if(mChildren[i]->CanSave(pHelper))
            mChildren[i]->Save(pThis,pHelper);
    }
}

void CAttachManager::SSplit::LoadChildren(xml::CNode pThis,SSaveHelper *pHelper)
{
    for(auto lChild : pThis.Children())
    {
        if(lChild.Name()=="hsplit")
        {
            AddChild(new SHSplit(mManager,lChild,pHelper));
        }
        else if(lChild.Name()=="vsplit")
        {
            AddChild(new SVSplit(mManager,lChild,pHelper));
        }
        else if(lChild.Name()=="scrollsplit")
        {
            AddChild(new SScrollSplit(mManager,lChild,pHelper));
        }
        else if(lChild.Name()=="csplit")
        {
            AddChild(new SCSplit(mManager,lChild,pHelper));
        }
        else if(lChild.Name()=="tabsplit")
        {
            AddChild(new STabSplit(mManager,lChild,pHelper));
        }
        else if(lChild.Name()=="client")
        {
            mManager->mClient=new SClient(mManager,lChild,pHelper);
            AddChild(mManager->mClient);
        }
        else if(lChild.Name()=="attachment")
        {
            SAttachment *lAttachment=new SAttachment(mManager,lChild,pHelper);
            mManager->mAttachments[lAttachment->mWindow]=lAttachment;
            AddChild(lAttachment);
        }
        else
        {
            msg_warn() << "unknown child in SSplit::LoadChildren\n";
        }
    }
}

////////////////////////////////
///////// SResizeSplit /////////
////////////////////////////////

CAttachManager::SResizeSplit::SResizeSplit(CAttachManager *pManager)
                : SSplit(pManager),mAbs(0),mPerc(0),mMax(1000)
{
}

CAttachManager::SResizeSplit::~SResizeSplit()
{
}

void CAttachManager::SResizeSplit::SetPos(double pPerc,double pAbs)
{
    mAbs=pAbs;
    mPerc=pPerc;
}

void CAttachManager::SResizeSplit::PlaceResizeBar(const CRect_d &pRect)
{
    if(!mBar)
    {
        mBar=new CTransparentResizeBar();
        mBar->sResized.Connect(&CAttachManager::SResizeSplit::OnResizeBar,this,_1);
        mManager->Window()->Place(mBar);
    }

    msg_info() << "placing resize bar at " << pRect << "\n";
    mBar->Show();
    mBar->Map(pRect.TopLeft(),pRect.Size(),false);
    mBar->BringToTop();
}

void CAttachManager::SResizeSplit::HideResizeBar()
{
    if(mBar)
    {
        mBar->Unmap();
        mBar->Hide();
    }
}

bool CAttachManager::SResizeSplit::CanSave(SSaveHelper *pHelper)
{
    return (mChildren[0]->CanSave(pHelper)||mChildren[1]->CanSave(pHelper));
}

///////////////////////////
///////// SHSplit /////////
///////////////////////////

CAttachManager::SHSplit::SHSplit(CAttachManager *pManager,
                    SPart *p1,SPart *p2)
    : SResizeSplit(pManager)
{
    AddChild(p1);
    AddChild(p2);
}

CAttachManager::SHSplit::SHSplit(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SResizeSplit(pManager)
{
    mAbs=pNode.GetDoubleAttrib("abs");
    mPerc=pNode.GetDoubleAttrib("perc");
    mMax=pNode.GetDoubleAttrib("max");

    LoadChildren(pNode,pHelper);
}

void CAttachManager::SHSplit::PlaceAttachment(SAttachment *pAttachment,EAttachPlace pPlace)
{
    if(pAttachment->GetFlags()&ATTACH_MENUBAR)
    {
        AttachHere(pAttachment,PlaceToRelative(pPlace));
    }
    else if(mChildren[0]->GetFlags()&(ATTACH_MENUBAR|ATTACH_TOOLBAR))
    {
        mChildren[1]->PlaceAttachment(pAttachment,pPlace);
    }
    else if(mChildren[1]->GetFlags()&ATTACH_STATUSBAR)
    {
        mChildren[0]->PlaceAttachment(pAttachment,pPlace);
    }
    else if(pAttachment->GetFlags()&ATTACH_STATUSBAR)
    {
        AttachHere(pAttachment,PlaceToRelative(pPlace));
    }
    else
    {
        if(pPlace==ATTACH_NORTH)
        {
            mChildren[0]->AttachHere(pAttachment,ATTACH_NORTH_OF);
        }
        else if(pPlace==ATTACH_SOUTH)
        {
            if(mChildren[1]->GetDesiredPlace()==ATTACH_SOUTH)
            {
                mChildren[1]->AttachHere(pAttachment,ATTACH_EAST_OF);
            }
            else
            {
                mChildren[1]->AttachHere(pAttachment,ATTACH_SOUTH_OF);
            }
        }
        else
        {
            AttachHere(pAttachment,PlaceToRelative(pPlace));
        }
    }
}

void CAttachManager::SHSplit::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    if(!mChildren[0]->IsVisible())
    {
        HideResizeBar();
        mChildren[1]->Reshape(mRect);
        return;
    }
    else if(!mChildren[1]->IsVisible())
    {
        HideResizeBar();
        mChildren[0]->Reshape(mRect);
        return;
    }

    int lMiddle=(int)clamp(mRect.t+mPerc*mRect.h()+mAbs,mRect.t,mRect.b);

    bool lResize=(mChildren[0]->CanResizeV()&&mChildren[1]->CanResizeV());
    int lResizeWidth=(int)get_default_theme()->GetResizeBarWidth(CTheme::DRAW_NONE);

    mChildren[0]->Reshape(CRect_d(mRect.l,mRect.t,mRect.r,lMiddle));

    if(lResize)
    {
        PlaceResizeBar(CRect_d(mRect.l,lMiddle-lResizeWidth/2,mRect.r,lMiddle+lResizeWidth/2));
        mBar->SetPointer(CPointer::STOCK_HSPLIT);
    }
    else
    {
        HideResizeBar();
    }

    mChildren[1]->Reshape(CRect_d(mRect.l,lMiddle,mRect.r,mRect.b));
}

void CAttachManager::SHSplit::ReshapeHidden()
{
    HideResizeBar();

    mHidden=true;
    for (int i=0;i<mChildren.size();i++)
        mChildren[i]->ReshapeHidden();
}

void CAttachManager::SHSplit::OnResizeBar(const CPoint_d &pP)
{
    mAbs+=pP.y;
    mManager->Window()->Relayout(true);
}

bool CAttachManager::SHSplit::CanResizeV()
{
    return ((mChildren[0]->IsVisible()&&mChildren[0]->CanResizeV())||
            (mChildren[1]->IsVisible()&&mChildren[1]->CanResizeV()));
}

bool CAttachManager::SHSplit::CanResizeH()
{
    return (!(mChildren[0]->IsVisible()&&!mChildren[0]->CanResizeH())&&
            !(mChildren[1]->IsVisible()&&!mChildren[1]->CanResizeH()));
}

void CAttachManager::SHSplit::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    if(mChildren[0]->CanSave(pHelper))
    {
        if(mChildren[1]->CanSave(pHelper))
        {
            xml::CNode lNode=pParent.NewChild("hsplit");

            lNode.SetDoubleAttrib("abs",mAbs);
            lNode.SetDoubleAttrib("perc",mPerc);
            lNode.SetDoubleAttrib("max",mMax);

            SaveChildren(lNode,pHelper);
        }
        else
        {
            mChildren[0]->Save(pParent,pHelper);
        }
    }
    else
    {
        mChildren[1]->Save(pParent,pHelper);
    }
}

///////////////////////////
///////// SVSplit /////////
///////////////////////////

CAttachManager::SVSplit::SVSplit(CAttachManager *pManager,
                    SPart *p1,SPart *p2)
    : SResizeSplit(pManager)
{
    AddChild(p1);
    AddChild(p2);
}

CAttachManager::SVSplit::SVSplit(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SResizeSplit(pManager)
{
    mAbs=pNode.GetDoubleAttrib("abs");
    mPerc=pNode.GetDoubleAttrib("perc");
    mMax=pNode.GetDoubleAttrib("max");

    LoadChildren(pNode,pHelper);
}

void CAttachManager::SVSplit::PlaceAttachment(
                            SAttachment *pAttachment,EAttachPlace pPlace)
{
    if(pPlace==ATTACH_WEST)
    {
        mChildren[0]->AttachHere(pAttachment,ATTACH_WEST_OF);
    }
    else if(pPlace==ATTACH_EAST)
    {
        mChildren[1]->AttachHere(pAttachment,ATTACH_EAST_OF);
    }
    else
    {
        AttachHere(pAttachment,PlaceToRelative(pPlace));
    }
}

void CAttachManager::SVSplit::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    if(!mChildren[0]->IsVisible())
    {
        HideResizeBar();
        mChildren[1]->Reshape(mRect);
        return;
    }
    else if(!mChildren[1]->IsVisible())
    {
        HideResizeBar();
        mChildren[0]->Reshape(mRect);
        return;
    }

    int lMiddle=(int)clamp(mRect.l+mPerc*mRect.w()+mAbs,mRect.l,mRect.r);

    bool lResize=(mChildren[0]->CanResizeH()&&mChildren[1]->CanResizeH());
    int lResizeWidth=(int)get_default_theme()->GetResizeBarWidth(CTheme::DRAW_NONE);

    mChildren[0]->Reshape(CRect_d(mRect.l,mRect.t,lMiddle,mRect.b));

    if(lResize)
    {
        PlaceResizeBar(CRect_d(lMiddle-lResizeWidth/2,mRect.t,lMiddle+lResizeWidth/2,mRect.b));
        mBar->SetPointer(CPointer::STOCK_VSPLIT);
    }
    else
    {
        HideResizeBar();
    }

    mChildren[1]->Reshape(CRect_d(lMiddle,mRect.t,mRect.r,mRect.b));
}

void CAttachManager::SVSplit::ReshapeHidden()
{
    HideResizeBar();

    mHidden=true;
    for (int i=0;i<mChildren.size();i++)
        mChildren[i]->ReshapeHidden();
}

void CAttachManager::SVSplit::OnResizeBar(const CPoint_d &pP)
{
    mAbs+=pP.x;
    mManager->Window()->Relayout(true);
}

bool CAttachManager::SVSplit::CanResizeH()
{
    return ((mChildren[0]->IsVisible()&&mChildren[0]->CanResizeH())||
            (mChildren[1]->IsVisible()&&mChildren[1]->CanResizeH()));
}

bool CAttachManager::SVSplit::CanResizeV()
{
    return (!(mChildren[0]->IsVisible()&&!mChildren[0]->CanResizeV())&&
            !(mChildren[1]->IsVisible()&&!mChildren[1]->CanResizeV()));
}

void CAttachManager::SVSplit::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    if(mChildren[0]->CanSave(pHelper))
    {
        if(mChildren[1]->CanSave(pHelper))
        {
            xml::CNode lNode=pParent.NewChild("vsplit");

            lNode.SetDoubleAttrib("abs",mAbs);
            lNode.SetDoubleAttrib("perc",mPerc);
            lNode.SetDoubleAttrib("max",mMax);

            SaveChildren(lNode,pHelper);
        }
        else
        {
            mChildren[0]->Save(pParent,pHelper);
        }
    }
    else
    {
        mChildren[1]->Save(pParent,pHelper);
    }
}

////////////////////////////////
///////// SScrollSplit /////////
////////////////////////////////

CAttachManager::SScrollSplit::SScrollSplit(CAttachManager *pManager,
                    SPart *pMain,SPart *pH,SPart *pV)
    : SSplit(pManager)
{
    AddChild(pMain);
    AddChild(pH);
    AddChild(pV);
}

CAttachManager::SScrollSplit::SScrollSplit(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SSplit(pManager)
{
    LoadChildren(pNode,pHelper);
}

void CAttachManager::SScrollSplit::PlaceAttachment(
                            SAttachment *pAttachment,EAttachPlace pPlace)
{
    AttachHere(pAttachment,PlaceToRelative(pPlace));
}

void CAttachManager::SScrollSplit::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    CRect_d lSmallRect(mRect);

    if(mChildren[1]->IsVisible())   //H
    {
        if(mChildren[1]->GetDesiredPlace()&ATTACH_NORTH)
            lSmallRect.t+=mChildren[1]->GetDesiredSize().y;
        else
            lSmallRect.b-=mChildren[1]->GetDesiredSize().y;
    }
    if(mChildren[2]->IsVisible())   //V
    {
        if(mChildren[2]->GetDesiredPlace()&ATTACH_WEST)
            lSmallRect.l+=mChildren[2]->GetDesiredSize().x;
        else
            lSmallRect.r-=mChildren[2]->GetDesiredSize().x;
    }

    mChildren[0]->Reshape(lSmallRect);
    if(mChildren[1]->GetDesiredPlace()&ATTACH_NORTH)
        mChildren[1]->Reshape(CRect_d(lSmallRect.l,mRect.t,lSmallRect.r,lSmallRect.t));
    else
        mChildren[1]->Reshape(CRect_d(lSmallRect.l,lSmallRect.b,lSmallRect.r,mRect.b));

    if(mChildren[2]->GetDesiredPlace()&ATTACH_WEST)
        mChildren[2]->Reshape(CRect_d(mRect.l,lSmallRect.t,lSmallRect.l,lSmallRect.b));
    else
        mChildren[2]->Reshape(CRect_d(lSmallRect.r,lSmallRect.t,mRect.r,lSmallRect.b));
}

bool CAttachManager::SScrollSplit::CanResizeH()
{
    return mChildren[0]->CanResizeH();
}

bool CAttachManager::SScrollSplit::CanResizeV()
{
    return mChildren[0]->CanResizeV();
}

void CAttachManager::SScrollSplit::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    xml::CNode lNode=pParent.NewChild("scrollsplit");

    SaveChildren(lNode,pHelper);
}

bool CAttachManager::SScrollSplit::CanSave(SSaveHelper *pHelper)
{
    return (mChildren[0]->CanSave(pHelper)||mChildren[1]->CanSave(pHelper)||
            mChildren[2]->CanSave(pHelper));
}

///////////////////////////
///////// SCSplit /////////
///////////////////////////

CAttachManager::SCSplit::SCSplit(CAttachManager *pManager,
                    SPart *p1,SPart *p2)
    : SSplit(pManager)
{
    AddChild(p1);
    AddChild(p2);
}

CAttachManager::SCSplit::SCSplit(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SSplit(pManager)
{
    LoadChildren(pNode,pHelper);
}

void CAttachManager::SCSplit::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    if(!mChildren[0]->IsVisible())
    {
        mChildren[1]->Reshape(mRect);
        return;
    }

    mChildren[0]->Reshape(mRect);
    mChildren[1]->Reshape(CRect_d(mRect.TopLeft(),CSize_d(0,0)));
}

void CAttachManager::SCSplit::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    if(mChildren[0]->CanSave(pHelper))
    {
        if(mChildren[1]->CanSave(pHelper))
        {
            xml::CNode lNode=pParent.NewChild("csplit");

            SaveChildren(lNode,pHelper);
        }
        else
        {
            mChildren[0]->Save(pParent,pHelper);
        }
    }
    else
    {
        mChildren[1]->Save(pParent,pHelper);
    }
}

bool CAttachManager::SCSplit::CanSave(SSaveHelper *pHelper)
{
    return (mChildren[0]->CanSave(pHelper)||mChildren[1]->CanSave(pHelper));
}

/////////////////////////////
///////// STabSplit /////////
/////////////////////////////

CAttachManager::STabSplit::STabSplit(CAttachManager *pManager,
                    SPart *p1,SPart *p2)
    : SSplit(pManager),mCurrent(0)
{
    AddChild(p1);
    AddChild(p2);
}

CAttachManager::STabSplit::STabSplit(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SSplit(pManager),mCurrent(0),mTab(nullptr)
{
    LoadChildren(pNode,pHelper);
}

void CAttachManager::STabSplit::AttachHere(SAttachment *pAttachment,EAttachRelative pPlace)
{
    if(pPlace==ATTACH_TAB_WITH)
    {
        AddChild(pAttachment);
    }
    else
    {
        SSplit::AttachHere(pAttachment,pPlace);
    }
}

void CAttachManager::STabSplit::OnChildRemoved(int i)
{
    if(i==mCurrent&&i>=mChildren.size())
    {
        mCurrent=mChildren.size()-1;
    }
}

void CAttachManager::STabSplit::Redraw()
{
    if(mTab)
        mTab->Refresh();
}

void CAttachManager::STabSplit::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    int lVisibleCount=0;
    int lFirstVisible=-1;

    for(int i=0;i<mChildren.size();i++)
    {
        if(mChildren[i]->IsVisible())
        {
            lVisibleCount++;
            if(lFirstVisible<0)
                lFirstVisible=i;
        }
    }

    if(!mChildren[mCurrent]->IsVisible()&&lFirstVisible>=0)
    {
        mCurrent=lFirstVisible;
    }

    CRect_d lRect=mRect;

    if(lVisibleCount>1)
        lRect.b-=16;

    for(int i=0;i<mChildren.size();i++)
    {
        if(i==mCurrent)
        {
            mChildren[i]->Reshape(lRect);
        }
        else
        {
            mChildren[i]->ReshapeHidden();
        }
    }

    if(lVisibleCount>1)
    {
        if(!mTab)
        {
            mTab=new STab(this);
            mManager->Window()->Place(mTab);
        }
        mTab->Map({mRect.l,mRect.b-16},{mRect.w(),16},false);
        mTab->Refresh();
        mTab->Show();
    }
    else if(mTab)
    {
        mTab->Hide();
    }
}

void CAttachManager::STabSplit::ReshapeHidden()
{
    mTab->Hide();

    mHidden=true;
    for (int i=0;i<mChildren.size();i++)
        mChildren[i]->ReshapeHidden();
}

void CAttachManager::STabSplit::OnTab(int pWhich)
{
    if(mCurrent==pWhich) return;
    mCurrent=pWhich;
    Reshape(mRect);
}

void CAttachManager::STabSplit::ActivateChild(SPart *pChild)
{
    for(int i=0;i<mChildren.size();i++)
    {
        if(pChild==mChildren[i])
        {
            OnTab(i);
            return;
        }
    }
}

bool CAttachManager::STabSplit::CanResizeH()
{
    return (mChildren[mCurrent]->CanResizeH());
}

bool CAttachManager::STabSplit::CanResizeV()
{
    return (mChildren[mCurrent]->CanResizeV());
}

void CAttachManager::STabSplit::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    xml::CNode lNode=pParent.NewChild("tabsplit");

    SaveChildren(lNode,pHelper);
}

bool CAttachManager::STabSplit::CanSave(SSaveHelper *pHelper)
{
    for(int i=0;i<mChildren.size();i++)
        if(mChildren[i]->CanSave(pHelper)) return true;
    return false;
}

/////////////////////////
///////// SRoot /////////
/////////////////////////

CAttachManager::SRoot::SRoot(CAttachManager *pManager,
                    SPart *pPart)
    : SSplit(pManager)
{
    AddChild(pPart);
}

CAttachManager::SRoot::SRoot(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SSplit(pManager)
{
    LoadChildren(pNode,pHelper);
}

void CAttachManager::SRoot::FindRelocation(SRelocation &pRelocation,
                                                    bool pDescend)
{
    pRelocation.mDestination=nullptr;
    pRelocation.mZone=ATTACH_RELATIVE_NONE;
    pRelocation.mRect=CRect_d(nUndefined);

    if(pDescend&&mRect.Contains(pRelocation.mPoint))
    {
        mChildren[0]->FindRelocation(pRelocation,true);
    }
}

void CAttachManager::SRoot::PlaceAttachment(
                            SAttachment *pAttachment,EAttachPlace pPlace)
{
    return mChildren[0]->PlaceAttachment(pAttachment,pPlace);
}

void CAttachManager::SRoot::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

/*    CWindow *lW=mManager->Window();
    if(lW->IsTopLevel()&&lW->GetAttrib(CWindow::ATTRIB_CUSTOMDECORATION)&&
        !get_toolkit()->SupportsBuolaWMExtensions())
    {
        ShowDecoration(true);
        mRect.t+=22;
    }
    else
    {
        ShowDecoration(false);
    }
*/
    ShowDecoration(false);

    mChildren[0]->Reshape(mRect);
}

void CAttachManager::SRoot::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    xml::CNode lNode=pParent.NewChild("root");

    SaveChildren(lNode,pHelper);
}

void CAttachManager::SRoot::ShowDecoration(bool pShow)
{
    if(pShow)
    {
        if(!mDecoration)
        {
            mDecoration=new SDecoration(this);
            mManager->Window()->Place(mDecoration);
            mResizeCorner=new SResizeCorner(this);
            mManager->Window()->Place(mResizeCorner);
        }
        mDecoration->Map({mRect.l,mRect.t},{mRect.w(),22},false);
        mResizeCorner->Map({mRect.r-10,mRect.b-10},{10,10},false);
        mDecoration->Show();
        mResizeCorner->Show();
        mResizeCorner->BringToTop();
    }
    else
    {
        if(mDecoration)
            mDecoration->Hide();
    }
}

///////////////////////////
///////// SClient /////////
///////////////////////////

CAttachManager::SClient::SClient(CAttachManager *pManager)
            : SPart(pManager)
{
}

CAttachManager::SClient::SClient(CAttachManager *pManager,xml::CNode,SSaveHelper*)
    : SPart(pManager)
{
}

void CAttachManager::SClient::Save(xml::CNode pParent,SSaveHelper*)
{
    pParent.NewChild("client");
}

///////////////////////////////
///////// SAttachment /////////
///////////////////////////////

CAttachManager::SAttachment::SAttachment(CAttachManager *pManager,const PWindow &pWindow,EAttachFlags pFlags,
                                         EAttachPlace pDesiredPlace)
    :   SPart(pManager)
    ,   mWindow(pWindow)
    ,   mFlags(pFlags)
    ,   mDesiredSize(pWindow->PreferredSize())
    ,   mDesiredPlace(pDesiredPlace)
{
    if(mDesiredSize.Undefined())
        mDesiredSize=pWindow->Size();

    mRelocation.mDestination=nullptr;
    mRelocation.mZone=ATTACH_RELATIVE_NONE;
    mRelocation.mRect=CRect_d(nUndefined);
}

CAttachManager::SAttachment::SAttachment(CAttachManager *pManager,
                                    xml::CNode pNode,SSaveHelper *pHelper)
    : SPart(pManager),mHandle(nullptr)
{
    mWindow=pHelper->NameToWindow(pNode.GetWStringAttrib("window"));

    if(mWindow->Parent()!=mManager->Window())
        mManager->Window()->Place(mWindow);

    mFlags=(EAttachFlags)pNode.GetIntAttrib("flags");
    mDesiredSize.x=pNode.GetDoubleAttrib("desiredw");
    mDesiredSize.y=pNode.GetDoubleAttrib("desiredh");
    mDesiredPlace=(EAttachPlace)pNode.GetIntAttrib("desiredplace");

    mRelocation.mDestination=nullptr;
    mRelocation.mZone=ATTACH_RELATIVE_NONE;
    mRelocation.mRect=CRect_d(nUndefined);
}

CAttachManager::SAttachment::~SAttachment()
{
}

void CAttachManager::SAttachment::DrawMark(const CRect_d &pRect,bool pTab)
{
    ///\todo this in some other way
    /*
    img::CGC *lGC=mManager->Window()->GetPhysical()->GetGC();
    ///\todo
    //lGC->SetSubwindow(true);
    
    CRect_d lRect;
    
    lGC->SetOperator(img::ECompOp::OVER);
    
    if(pRect.Undefined())
    {
        lRect=mRect;
        lGC->SetSource(img::rgba8(120,120,180,100));
        pTab=false;
    }
    else
    {
        lRect=pRect;
        lGC->SetSource(img::rgba8(120,180,120,100));
    }
    
    if(pTab)
    {
        lGC->Path().Rect(CPoint_d(lRect.l,lRect.t),CSize_d(5,lRect.h()-20));
        lGC->Path().Rect(CPoint_d(lRect.l+5,lRect.t),CSize_d(lRect.w()-10,5));
        lGC->Path().Rect(CPoint_d(lRect.r-5,lRect.t),CSize_d(5,lRect.h()));
        lGC->Path().Rect(CPoint_d(lRect.l+5,lRect.b-25),CSize_d(lRect.w()-80,5));
        lGC->Path().Rect(CPoint_d(lRect.r-75,lRect.b-25),CSize_d(5,25));
        lGC->Path().Rect(CPoint_d(lRect.r-70,lRect.b-5),CSize_d(65,5));
        // filled alternative:
        //      lGC->Path().Rect(CPoint_d(lRect.r-75,lRect.b-25),CSize_d(70,25));
    }
    else
    {
        lGC->Path().Rect(CPoint_d(lRect.l,lRect.t),CSize_d(5,lRect.h()));
        lGC->Path().Rect(CPoint_d(lRect.l+5,lRect.t),CSize_d(lRect.w()-10,5));
        lGC->Path().Rect(CPoint_d(lRect.r-5,lRect.t),CSize_d(5,lRect.h()));
        lGC->Path().Rect(CPoint_d(lRect.l+5,lRect.b-5),CSize_d(lRect.w()-10,5));
    }
    
    lGC->FillPath();
    */
}

void CAttachManager::SAttachment::UndrawMark(const CRect_d&)
{
    ///\todo find out how we can do this... what don't expose meant
    //mManager->Window()->Refresh(CWindow::REFRESH_DONTEXPOSE|CWindow::REFRESH_CHILDREN|CWindow::REFRESH_IMMEDIATE);
}

void CAttachManager::SAttachment::Redraw()
{
    if(mHandle)
        mHandle->Refresh();
}

void CAttachManager::SAttachment::Reshape(const CRect_d &pRect)
{
    mHidden=false;
    mRect=pRect;

    if(mFlags&ATTACH_BAR)
    {
        double lWidth=get_default_theme()->GetAttachHandleWidth(mFlags);

        mWindow->Map({mRect.l,mRect.t+lWidth},{mRect.w(),mRect.h()-lWidth},false);
        if(pRect.h()>0&&pRect.w()>0)
            PlaceHandle(CRect_d(mRect.l,mRect.t,mRect.r,mRect.t+lWidth));
        else
            HideHandle();
    }
    else
    {
        mWindow->Map(mRect.TopLeft(),mRect.Size(),false);
    }
}

void CAttachManager::SAttachment::ReshapeHidden()
{
    HideHandle();
    ///\todo this would be just a map now
    //mWindow->LayoutShow(false);
    mHidden=true;
}

bool CAttachManager::SAttachment::IsVisible()
{
    return mWindow->Mappable();
}

void CAttachManager::SAttachment::ResizeBy(const CSize_d &pInc)
{
    mDesiredSize+=pInc;
}

void CAttachManager::SAttachment::PlaceHandle(const CRect_d &pRect)
{
    if(!mHandle)
    {
        mHandle=new CHandleBar;
        mManager->Window()->Place(mHandle);
        ///\todo it will probably be a widget (or have some specialized property)
        //mHandle->SetStyleBit(CHandleBar::STYLE_CLOSEBUTTON|CHandleBar::STYLE_WHOLEBAR);
        //mHandle->SetCaption(mWindow->GetTitle());
        mHandle->sStartMove.Connect(&SAttachment::OnStartMove,this,_1);
        mHandle->sContinueMove.Connect(&SAttachment::OnContinueMove,this,_1);
        mHandle->sEndMove.Connect(&SAttachment::OnEndMove,this);
        mHandle->eClose.Connect([this]{mWindow->Close(false);});
        mHandle->eDock.Connect(&CAttachManager::Undock,mManager,mWindow);
    }
    mHandle->Map(pRect.TopLeft(),pRect.Size(),false);
    mHandle->Show();
}

void CAttachManager::SAttachment::HideHandle()
{
    if(mHandle)
        mHandle->Hide();
}

bool CAttachManager::SAttachment::CanSave(SSaveHelper *pHelper)
{
    return (!pHelper->WindowToName(mWindow).empty());
}

void CAttachManager::SAttachment::Save(xml::CNode pParent,SSaveHelper *pHelper)
{
    xml::CNode lNode=pParent.NewChild("attachment");

    lNode.SetStringAttrib("window",pHelper->WindowToName(mWindow));
    lNode.SetDoubleAttrib("desiredw",mDesiredSize.x);
    lNode.SetDoubleAttrib("desiredh",mDesiredSize.y);
    lNode.SetIntAttrib("desiredplace",mDesiredPlace);
    if(mWindow->Mapped())
        mFlags|=ATTACH_SHOW;
    else
        mFlags&=~ATTACH_SHOW;
    lNode.SetIntAttrib("flags",mFlags);
}

void CAttachManager::SAttachment::OnStartMove(const CPoint_d&)
{
    DrawMark(CRect_d(nUndefined),false);
}

void CAttachManager::SAttachment::OnContinueMove(const CPoint_d &pPoint)
{
    CRect_d lOldRect=mRelocation.mRect;
    mRelocation.mPoint=pPoint-mManager->Window()->GetRootPos();
    mRelocation.mRelocated=this;
    
    mManager->mRoot->FindRelocation(mRelocation);
    
    if(mRelocation.mRect!=lOldRect)
    {
        UndrawMark(lOldRect);
        DrawMark(mRelocation.mRect,mRelocation.mTab);
    }
}

void CAttachManager::SAttachment::OnEndMove()
{
    UndrawMark(mRelocation.mRect);
    
    if(mRelocation.mDestination)
    {
        SSplit *lOldParent=mParent;
        
        if(mRelocation.mZone&(ATTACH_SOUTH|ATTACH_NORTH|ATTACH_EAST|ATTACH_WEST|ATTACH_TAB))
        {
            mRelocation.mDestination->AttachHere(this,mRelocation.mZone);
                                                 
            lOldParent->RemoveChild(this);
            ///\todo this
            //mManager->Window()->OnLayoutChange();
        }
    }
    
    mRelocation.mDestination=nullptr;
    mRelocation.mZone=ATTACH_RELATIVE_NONE;
    mRelocation.mRect=CRect_d(nUndefined);
}

/*namespace gui*/ } /*namespace buola*/ }
